/********************************************************************************
* 
*	Project Name : S3C6410 Validation
*
*	Copyright 2008 by Samsung Electronics, Inc.
*	All rights reserved.
*
*	Project Description :
*		This software is only for verifying functions of the S3C6400.
*		Anybody can use this software without our permission.
*  
*--------------------------------------------------------------------------------
* 
*	File Name : AC97.c
*  
*	File Description :
*
*	Author	: Sung-Hyun, Na
*	Dept. : AP Development Team
*	Created Date : 2008/10/24
*	Version : 0.2
* 
*	History
*	- Version 0.1 (2007/03/09)
*	  -> Only available with STAC9767 AC97 Codec.
*   - Version 0.2 (2007/04/04)
*     -> Working with WM9713 AC97 Codec.
*
********************************************************************************/

#ifndef __AC97_H__
#define __AC97_H__
 
  
#ifdef __cplusplus
extern "C" {
#endif

#include "def.h"
#include "sfr6410.h"
#include "library.h"
#include "gpio.h"
#include "Option.h"
#include "dma.h"
#include "Sysc.h"
#include "audio.h"


#define AC97_CODEC							WM9713

#define AC97_DebugDelay						500
#define AC97_CMDReadDelay					500
#define AC97_CMDWriteDelay					500

#define AC97_REC_LEN 						0x100000
#define REC_BUF  							CODEC_MEM_ST	//0x51000000
#define PCM_OUT_TRIGGER 					5
#define PCM_IN_TRIGGER 						5
#define MIC_IN_TRIGGER						5

#define ENABLE						(1)
#define DISABLE						(0)



#define AC97_Enable_Transfer_ACLINK			(1 << 3)
#define AC97_Enable_ACLINK					(1 << 2)
#define AC97_Enable_Warm_Reset				(1 << 1)
#define AC97_Enable_Cold_Reset				(1 << 0)

enum AC97_SFR
{
	rACGLBCTRL 		= 0x0,		// AC97 Global Control Register (R/W)
	rACGLBSTAT 		= 0x4,		// AC97 Global Status Register (R)
	rACCODECCMD 	= 0x8,		// AC97 Codec Command Register (R/W)
	rACCODECSTAT 	= 0xc,   		// AC97 Codec Status Register (R)
	rACPCMADDR 	= 0x10,		// AC97 PCM Out/In Channel FIFO Address Register (R)
	rACMICADDR		= 0x14,		// AC97 MIC in Channel FIFO Address Register (R)
	rACPCMDATA	 	= 0x18,		// AC97 PCM Out/In Channel FIFO Data Register (R/W)
	rACMICDATA	 	= 0x1c		// AC97 MIC in Channel FIFO Data Register (R/W)
};

typedef enum
{
	State_Idle = 0,
	State_Init = 1,
	State_Ready = 2,
	State_Active = 3,
	State_LP = 4,
	State_Warm = 5
}AC97_State;

typedef enum 
{
	PORT0, PORT1
}AC97_PORT;

typedef enum 
{
	CODEC_READY_INT 		= (1 << 6), 
	PCMOUT_UNDERRUN_INT	= (1 << 5), 
	PCMIN_OVERRUN_INT 		= (1 << 4), 
	MICIN_OVERRUN_INT		= (1 << 3), 
	PCMOUT_THRESHOLD_INT	= (1 << 2), 
	PCMIN_THRESHOLD_INT	= (1 << 1), 
	MICIN_THRESHOLD_INT	= (1 << 0) 
}AC97_INT;

typedef enum 
{
	WRITE = 0, 
	READ = 1
}AC97_CMD;

typedef enum 
{
	PCM_OUT = 12,
	PCM_IN = 10, 
	MIC_IN = 8,
	PCM_InOut = 4,
	MIC_InOut = 2
}AC97_CHANNEL;

typedef enum 
{
	OFF = 0, 
	PIO = 1, 
	DMA = 2
}AC97_TRANSFER_MODE;

#if 0//For AC97 SFR W/R Test
REGINFO		sAc97RegInfo[] = 
{ 

	{"			", AC97_BASE+0x00, 32, RW, DPDB, 0, 0},   
	{"			", AC97_BASE+0x04, 32, RW, DPDB, 0, 0},
	{"			", AC97_BASE+0x08, 32, RW, DPDB, 0, 0},
	{"			", AC97_BASE+0x10, 32, RW, DPDB, 0, 0},   
	{"			", AC97_BASE+0x14, 32, RW, DPDB, 0, 0},
	{"			", AC97_BASE+0x18, 32, RW, DPDB, 0, 0},
	{"			", AC97_BASE+0x1C, 32, RW, DPDB, 0, 0},   

};
#endif

typedef struct AC97testFuncMenu {
	u8 (*func)(AUDIO_PORT); 
	const char *desc;
} AC97testFuncMenu;

//Define Member Structure
typedef struct
{
	//Private Variable for ISR
	u32					m_uNumInt;
	volatile u8			m_usCodecReady;
	volatile u8			m_usAC97PCMInDone;
	volatile u8			m_usAC97MICInDone;
	volatile u8			m_usAC97PCMOutDone;
	volatile u8			m_usCmdHold;	
	volatile u32*			m_pMemPcmIn;
	volatile u32*			m_pMemMicIn;
	volatile u32*			m_pMemPcmOut;
	s32 					m_uPCMInBufferPointer;
	s32 					m_uPCMOutBufferPointer;
	s32 					m_uMICInBufferPointer;
	//Recoding & Playing Buffer Address
	u32*				m_pPCMInStartAddr;
	u32*				m_pPCMOutStartAddr;	
	u32*				m_pMICInStartAddr;	
	s32					m_uPCMInSize;
	s32					m_uPCMOutSize;
	s32					m_uMICInSize;	
	//DMA
	u32 					m_uNumDma;
	DMA_UNIT 			m_eDmaUnit;	
	DMA_CH 			m_eAc97PCMInCh;	
	DMA_CH 			m_eAc97PCMOutCh;	
	DMA_CH 			m_eAc97MICInCh;	
	DMAC				m_oAc97PcmInDma;
	DMAC				m_oAc97PcmOutDma;
	DMAC				m_oAc97MicInDma;		
	//IP Operating Information
	AC97_INT			m_ePCMInIntMode;
	AC97_INT			m_ePCMOutIntMode;
	AC97_INT			m_eMICInIntMode;
	//CLK
	u32					m_uSamplingRate;	
	//Codec Operating Information
	AudioCodec			m_uCodecID;
	AudioSource			m_eADCSource;	
	s32					m_uInputVolume;
	s32					m_uOutputVolume;		
}AC97_Infor;

AC97_Infor* AC97_GetInfor(void);
void AC97_Init(void);
void AC97_SetIntrDone(AC97_INT eInt, u8 usBool);
u8 AC97_GetIntrDone(AC97_INT eInt);
void AC97_InitBuffer(AC97_CHANNEL, u32*, u32);
s32 AC97_PutDataMem(AC97_CHANNEL eCh, u32 uData);
s32 AC97_PopDataMem(AC97_CHANNEL eCh, u32*);
void AC97_InitDMA(AC97_CHANNEL);
void AC97_DMAStop(AC97_CHANNEL);
void AC97_DMAIntrClr(AC97_CHANNEL);

void AC97_SetDMAUnit(DMA_UNIT eUnit);
void AC97_SetIntrMode(AC97_CHANNEL, AC97_INT);
//API of Audio Port
u8 AC97_SetPort(AUDIO_PORT ePort);
u8 AC97_ClosePort(AUDIO_PORT ePort);
/*---------------------------------- APIs of rGLBCTRL ---------------------------------*/
u8 AC97_InitACLINK(void);
void AC97_WarmReset(void);
void AC97_ColdReset(void);
void AC97_ShuntOffAcLink(void);
void AC97_SetTransferCh(AC97_CHANNEL eCh, AC97_TRANSFER_MODE eTransferMode);
void AC97_IntrClr(AC97_INT eIntStatus);
void AC97_IntrCon(AC97_INT eInt, u8 usBool);
void AC97_ClearInt(AC97_INT eInt);
/*---------------------------------- APIs of rGLBSTAT ---------------------------------*/
AC97_State AC97_ControllerState(void);
u32 AC97_InterruptState(void);
/*---------------------------------- APIs of rCODEC_CMD and rCODEC_STAT ---------------------------------*/
u16 AC97_CodecCmd(AC97_CMD eCmd, u8 uCmdOffset, u16 uCmdData);
void AC97_CodecCmdManually(void);
void AC97_CodecCmdNoDelay(AC97_CMD, u8, u16);
void AC97_CodecStatRegister(u16*, u16*);
/*---------------------------------- APIs of rPCMADDR & rMICADDR---------------------------*/
u32 AC97_GetFifoAddr(AC97_CHANNEL eCh);
void AC97_SetFifoAddr(AC97_CHANNEL eCh, u8 uAddr);
/*---------------------------- APIs of rPCMDATA & rACMICDATA-------------------------*/
void AC97_SetDataFifo(u32 uPCMData);
u32 AC97_GetDataFifo(AC97_CHANNEL eCh);
/*---------------------------------- APIs of ISR for AC97 ---------------------------------*/
void __irq ISR_AC97(void);
void Isr_AC97CodecReady(void);
void Isr_AC97PCMOUT_UNDERRUN_INT(void);
void Isr_AC97PCMIN_OVERRUN_INT(void);
void Isr_AC97MICIN_OVERRUN_INT(void);
void Isr_AC97PCMOUT_THRESHOLD_INT(void);
void Isr_AC97PCMIN_THRESHOLD_INT(void);
void Isr_AC97MICIN_THRESHOLD_INT(void);
/*---------------------------------- APIs of ISR for DMA by AC97 Request ---------------------------------*/
void __irq Isr_AC97DmaRestart(void);
void __irq Isr_AC97DmaDone(void);
void AC97_DMADone(AC97_CHANNEL eCh);
void AC97_DMARestart(AC97_CHANNEL eCh);
/*---------------------------------- APIs of AC97 Codec ---------------------------------*/
void AC97_CodecInitPD(void);
u8 AC97_SetOutputVolume(u8 uUpDownVolume);
void AC97_ExitCodecPCMOut(void);
void AC97_ExitCodecPCMIn(u16 uDACsOff);
void AC97_ExitCodecMICIn(u16 uDACsOff);
#ifdef __cplusplus
}
#endif

#endif /*__AC97_H__*/

